﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Plumbing;
using Autodesk.Revit.Exceptions;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using YArchitech.Controls;
using YArchitech.HVAC;
using YArchitech.Revit;

namespace YArchitech.Plumbing
{
	[Transaction(TransactionMode.Manual)]
	[Regeneration(RegenerationOption.Manual)]
	public class ChooseAndCopy : IExternalCommand
	{
		public Result Execute(ExternalCommandData commandData, ref string message, ElementSet Setelements)
		{
			Document document = commandData.Application.ActiveUIDocument.Document;
			UIDocument activeUIDocument = commandData.Application.ActiveUIDocument;
			UIApplication application = commandData.Application;
			Selection selection = activeUIDocument.Selection;
			if (!YJKRevitTools.ViewCheck(activeUIDocument, new List<ViewType>
			{
				(ViewType)1,
				(ViewType)2,
				(ViewType)4
			}))
			{
				return Autodesk.Revit.UI.Result.Cancelled;
			}
			Transaction transaction = new Transaction(document, "Copy");
			transaction.Start();
			try
			{
				Reference reference = selection.PickObject((Autodesk.Revit.UI.Selection.ObjectType)1, new DuctAndPipeFilter(), "请点取要选择的支管与立管的近端：");
				ConnectorSetIterator connectorSetIterator = (document.GetElement(reference) as Pipe).ConnectorManager.Connectors.ForwardIterator();
				connectorSetIterator.MoveNext();
				Connector connector = connectorSetIterator.Current as Connector;
				double num = connector.Origin.DistanceTo(reference.GlobalPoint);
				connectorSetIterator.MoveNext();
				Connector connector2 = connectorSetIterator.Current as Connector;
				double num2 = connector2.Origin.DistanceTo(reference.GlobalPoint);
				XYZ xyz = null;
				Connector connector3;
				Connector connector4;
				if (num > num2)
				{
					connector3 = connector;
					connector4 = connector2;
				}
				else
				{
					connector3 = connector2;
					connector4 = connector;
				}
				SearchBranch searchBranch = new SearchBranch(new ElementNode(document.GetElement(reference), connector4));
				searchBranch.DoSearch();
				ElementNode listRoot = searchBranch.GetListRoot();
				List<ElementNode> list = new List<ElementNode>();
				list = this.GetAllElemNode(listRoot, ref list);
				List<Element> list2 = new List<Element>();
				List<ElementId> list3 = new List<ElementId>();
				foreach (ElementNode elementNode in list)
				{
					if (!selection.GetElementIds().Contains(elementNode.Element.Id))
					{
						list2.Add(elementNode.Element);
						RevitVersionFuncs.AddToSelection(selection, elementNode.Element);
						list3.Add(elementNode.Element.Id);
					}
				}
				Element element = document.GetElement(reference);
				Level level = document.GetElement(element.GetParameter(BuiltInParameter.RBS_START_LEVEL_PARAM).AsElementId()) as Level;
				new List<Level>();
				List<Level> difLevels = this.GetDifLevels(document);
				difLevels.Sort((Level item1, Level item2) => item1.Elevation.CompareTo(item2.Elevation));
				ViewList viewList = new ViewList(difLevels, level);
				viewList.ShowDialog();
				if (viewList.DialogResult != DialogResult.OK)
				{
					viewList.Dispose();
					return Autodesk.Revit.UI.Result.Cancelled;
				}
				List<Level> selectedLevels = viewList.selectedLevels;
				if (!viewList.isOnCurrentRiserPipe)
				{
					Reference reference2;
					for (;;)
					{
						reference2 = selection.PickObject((Autodesk.Revit.UI.Selection.ObjectType)1, new DuctAndPipeFilter(), "请选择一个立管：");
						if (YJKRevitTools.isRiserPiping(document.GetElement(reference2)))
						{
							break;
						}
						YJKMessageBox.Error("请选择一个立管！");
					}
					xyz = ((document.GetElement(reference2) as Pipe).Location as LocationCurve).Curve.GetEndPoint(0);
				}
				double num3 = level.Elevation;
				double elevation = level.Elevation;
				foreach (Level level2 in selectedLevels)
				{
					double elevation2 = level2.Elevation;
					if (elevation2 < num3)
					{
						num3 = elevation2;
					}
				}
				foreach (Level level3 in selectedLevels)
				{
					Pipe pipe = null;
					XYZ xyz2 = null;
					if (viewList.isOnCurrentRiserPipe)
					{
						xyz2 = new XYZ(0.0, 0.0, level3.Elevation - level.Elevation);
						SearchBranch searchBranch2 = new SearchBranch(new ElementNode(document.GetElement(reference), connector3));
						searchBranch2.DoSearch();
						ElementNode listRoot2 = searchBranch2.GetListRoot();
						List<ElementNode> list4 = new List<ElementNode>();
						list = this.GetAllElemNode(listRoot2, ref list4);
						double num4 = double.PositiveInfinity;
						using (List<ElementNode>.Enumerator enumerator = list.GetEnumerator())
						{
							while (enumerator.MoveNext())
							{
								ElementNode elementNode2 = enumerator.Current;
								Element element2 = elementNode2.Element;
								if (element2.Category.Name == "管道" && YJKRevitTools.isRiserPiping(element2))
								{
									double num5 = (((element2 as Pipe).Location as LocationCurve).Curve as Line).Distance(new XYZ(connector3.Origin.X + xyz2.X, connector3.Origin.Y + xyz2.Y, connector3.Origin.Z + xyz2.Z));
									if (num5 < num4)
									{
										num4 = num5;
										pipe = (element2 as Pipe);
									}
								}
							}
							goto IL_597;
						}
						goto IL_450;
					}
					goto IL_450;
					IL_597:
					if (pipe == null)
					{
						YJKMessageBox.Warning("请选择距立管的近端或横管未连接，无法复制!");
						return Autodesk.Revit.UI.Result.Failed;
					}
					XYZ xyz3 = new XYZ(connector4.Origin.X + xyz2.X, connector4.Origin.Y + xyz2.Y, connector4.Origin.Z + xyz2.Z);
					Connector connector5 = null;
					Pipe pipe2 = null;
					ICollection<ElementId> collection = ElementTransformUtils.CopyElements(document, list3, xyz2);
					document.Regenerate();
					if (viewList.isRotated)
					{
						ElementTransformUtils.RotateElements(document, collection, (pipe.Location as LocationCurve).Curve as Line, -(viewList.angle / 180.0) * Math.PI);
					}
					double num6 = double.PositiveInfinity;
					foreach (ElementId elementId in collection)
					{
						Element element3 = document.GetElement(elementId);
						if (element3.Category.Name == "管道")
						{
							Pipe pipe3 = element3 as Pipe;
							YJKPiping<Pipe> hypiping = new YJKPiping<Pipe>(pipe3);
							double offSet = hypiping.GetOffSet();
							hypiping.SetLevel(level3.Id);
							hypiping.SetOffSet(offSet - (level3.Elevation - level.Elevation));
							double val = (pipe3.Location as LocationCurve).Curve.Tessellate()[0].DistanceTo(xyz3);
							double val2 = (pipe3.Location as LocationCurve).Curve.Tessellate()[1].DistanceTo(xyz3);
							if (Math.Min(val, val2) < num6)
							{
								num6 = Math.Min(val, val2);
								connector5 = new YJKPiping<Pipe>(pipe3).GetCloseConnector(xyz3, false);
								pipe2 = pipe3;
							}
						}
                        else if (element3.GetParameter(BuiltInParameter.FAMILY_LEVEL_PARAM) != null && !element3.GetParameter(BuiltInParameter.FAMILY_LEVEL_PARAM).IsReadOnly && element3.GetParameter((BuiltInParameter)(-1001364)) != null && !element3.GetParameter((BuiltInParameter)(-1001364)).IsReadOnly)
						{
							double num7 = element3.GetParameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM).AsDouble();
							Parameter parameter = element3.GetParameter(BuiltInParameter.FAMILY_LEVEL_PARAM);
							if (parameter != null && !parameter.IsReadOnly)
							{
								parameter.Set(level3.Id);
							}
							element3.GetParameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM).Set(num7 - (level3.Elevation - level.Elevation));
						}
					}
					YJKLine hyline = new YJKLine((pipe.Location as LocationCurve).Curve as Line);
					YJKPiping<Pipe> hypiping2 = new YJKPiping<Pipe>(pipe);
					bool flag = false;
					int num8 = 1;
					if ((xyz3.Z > hyline.StartPoint.Z && xyz3.Z > hyline.EndPoint.Z) || (xyz3.Z < hyline.StartPoint.Z && xyz3.Z < hyline.EndPoint.Z))
					{
						if (xyz3.Z < hyline.StartPoint.Z && xyz3.Z < hyline.EndPoint.Z)
						{
							num8 = -1;
						}
						flag = true;
					}
					YJKPipeConnectorHelper hypipeConnectorHelper = new YJKPipeConnectorHelper();
					string text = "";
					bool flag2 = true;
					if (flag)
					{
						if (hyline.EndPoint.DistanceTo(connector5.Origin) < hyline.StartPoint.DistanceTo(connector5.Origin))
						{
							if (!hypiping2.EndConnector.Connector.IsConnected)
							{
								hypiping2.Extend(hyline.StartPoint, new XYZ(hyline.EndPoint.X, hyline.EndPoint.Y, connector5.Origin.Z + (double)num8 * hypiping2.GetDiameter() * 6.0));
							}
							else
							{
								flag2 = false;
							}
						}
						else if (!hypiping2.StartConnector.Connector.IsConnected)
						{
							hypiping2.Extend(new XYZ(hyline.StartPoint.X, hyline.StartPoint.Y, connector5.Origin.Z + (double)num8 * hypiping2.GetDiameter() * 6.0), hyline.EndPoint);
						}
						else
						{
							flag2 = false;
						}
					}
					if (flag2)
					{
						FamilySymbol fsByCon = this.GetFsByCon(connector4);
						if (fsByCon == null || !fsByCon.Family.Name.Contains("顺水三通"))
						{
							new HYPipeConnect().NewSomeConnect(new List<Pipe>
							{
								pipe,
								pipe2
							});
						}
						else
						{
							hypipeConnectorHelper.TPipeConnectRPipe(pipe, pipe2, fsByCon, 1, ref text, false, 15.0);
						}
					}
					document.Regenerate();
					continue;
					IL_450:
					xyz2 = new XYZ(xyz.X - connector4.Origin.X, xyz.Y - connector4.Origin.Y, level3.Elevation - level.Elevation);
					List<Pipe> allRiserPipe = this.GetAllRiserPipe(document);
					double num9 = double.PositiveInfinity;
					foreach (Pipe pipe4 in allRiserPipe)
					{
						XYZ hyendPoint = (pipe4.Location as LocationCurve).Curve.GetEndPoint(0);
						if (Math.Abs(hyendPoint.X - xyz.X) < 0.0001 && Math.Abs(hyendPoint.Y - xyz.Y) < 0.0001)
						{
							double num10 = ((pipe4.Location as LocationCurve).Curve as Line).Distance(new XYZ(connector4.Origin.X + xyz2.X, connector4.Origin.Y + xyz2.Y, connector4.Origin.Z + xyz2.Z));
							if (num10 < num9)
							{
								num9 = num10;
								pipe = pipe4;
							}
						}
					}
					goto IL_597;
				}
				transaction.Commit();
			}
			catch (Autodesk.Revit.Exceptions.OperationCanceledException)
			{
				return Autodesk.Revit.UI.Result.Succeeded;
			}
			catch (Exception ex)
			{
				message = ex.Message;
				return Autodesk.Revit.UI.Result.Failed;
			}
			finally
			{
				if (transaction != null && (int)transaction.GetStatus() != 3 && (int)transaction.GetStatus() != 2)
				{
					transaction.RollBack();
				}
			}
			return Autodesk.Revit.UI.Result.Succeeded;
		}

		public List<Level> GetDifLevels(Autodesk.Revit.DB.Document doc)
		{
			List<Level> list = new List<Level>();
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			filteredElementCollector.OfClass(typeof(Autodesk.Revit.DB.View));
			foreach (Element element in filteredElementCollector)
			{
				Level genLevel = (element as Autodesk.Revit.DB.View).GenLevel;
				if (genLevel != null)
				{
					bool flag = true;
					foreach (Level level in list)
					{
						if (Math.Abs(genLevel.Elevation - level.Elevation) < 0.0001)
						{
							flag = false;
							break;
						}
					}
					if (flag)
					{
						list.Add(genLevel);
					}
				}
			}
			return list;
		}

		private FamilySymbol GetFsByCon(Connector con)
		{
			try
			{
				ConnectorSetIterator connectorSetIterator = con.AllRefs.ForwardIterator();
				connectorSetIterator.MoveNext();
				FamilyInstance familyInstance = (connectorSetIterator.Current as Connector).Owner as FamilyInstance;
				if (familyInstance == null)
				{
					connectorSetIterator.MoveNext();
					familyInstance = ((connectorSetIterator.Current as Connector).Owner as FamilyInstance);
				}
				if (familyInstance.MEPModel.ConnectorManager.Connectors.Size == 3)
				{
					return familyInstance.Symbol;
				}
				connectorSetIterator = familyInstance.MEPModel.ConnectorManager.Connectors.ForwardIterator();
				while (connectorSetIterator.MoveNext())
				{
					try
					{
						ConnectorSetIterator connectorSetIterator2 = (connectorSetIterator.Current as Connector).AllRefs.ForwardIterator();
						connectorSetIterator2.MoveNext();
						FamilyInstance familyInstance2 = (connectorSetIterator2.Current as Connector).Owner as FamilyInstance;
						if (familyInstance2 == null || familyInstance2.MEPModel.ConnectorManager.Connectors.Size != 3)
						{
							connectorSetIterator2.MoveNext();
							familyInstance2 = ((connectorSetIterator2.Current as Connector).Owner as FamilyInstance);
						}
						if (familyInstance2.MEPModel.ConnectorManager.Connectors.Size == 3)
						{
							return familyInstance2.Symbol;
						}
					}
					catch
					{
					}
				}
			}
			catch (Exception ex)
			{
				ex.ToString();
			}
			return null;
		}

		private List<Pipe> GetAllRiserPipe(Autodesk.Revit.DB.Document doc)
		{
			List<Pipe> list = new List<Pipe>();
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			filteredElementCollector.OfClass(typeof(Pipe));
			foreach (Element element in filteredElementCollector)
			{
				if (element.Category.Name == "管道")
				{
					Pipe pipe = element as Pipe;
					if (YJKRevitTools.isRiserPipe(pipe))
					{
						list.Add(pipe);
					}
				}
			}
			return list;
		}

		private Autodesk.Revit.DB.View GetElementView(Element e)
		{
			Autodesk.Revit.DB.View result = null;
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(e.Document);
			filteredElementCollector.OfClass(typeof(ViewPlan));
			foreach (Element element in filteredElementCollector)
			{
				Autodesk.Revit.DB.View view = element as Autodesk.Revit.DB.View;
				try
				{
					FilteredElementCollector filteredElementCollector2 = new FilteredElementCollector(e.Document, view.Id);
					filteredElementCollector2.OfClass(typeof(Pipe));
					IEnumerator<Element> enumerator2 = filteredElementCollector2.ToElements().GetEnumerator();
					{
						while (enumerator2.MoveNext())
						{
							if (enumerator2.Current.Id.IntegerValue.Equals(e.Id.IntegerValue))
							{
								result = view;
								return result;
							}
						}
					}
				}
				catch
				{
				}
			}
			return result;
		}

		private List<Autodesk.Revit.DB.View> GetSameTypeView(Autodesk.Revit.DB.View originView)
		{
			List<Autodesk.Revit.DB.View> list = new List<Autodesk.Revit.DB.View>();
			string b = "";
			string b2 = "";
			foreach (object obj in originView.Parameters)
			{
				Parameter parameter = (Parameter)obj;
				if (parameter.Definition.Name == "视图分类-子")
				{
					b2 = parameter.AsString();
				}
				if (parameter.Definition.Name == "视图分类-父")
				{
					b = parameter.AsString();
				}
			}
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(originView.Document);
			filteredElementCollector.OfClass(typeof(Autodesk.Revit.DB.View));
			foreach (Element element in filteredElementCollector)
			{
				Autodesk.Revit.DB.View view = element as Autodesk.Revit.DB.View;
				string a = "";
				string a2 = "";
				foreach (object obj2 in view.Parameters)
				{
					Parameter parameter2 = (Parameter)obj2;
					if (parameter2.Definition.Name == "视图分类-子")
					{
						a2 = parameter2.AsString();
					}
					if (parameter2.Definition.Name == "视图分类-父")
					{
						a = parameter2.AsString();
					}
				}
				if (a == b && a2 == b2)
				{
					foreach (object obj3 in view.Parameters)
					{
                        //((Parameter)obj3).Definition.Name == "视图样板";
					}
					if (view.GenLevel != null)
					{
						list.Add(view);
					}
				}
			}
			return list;
		}

		private List<ElementNode> GetAllElemNode(ElementNode eNode, ref List<ElementNode> listENode)
		{
			if (eNode == null)
			{
				return listENode;
			}
			listENode.Add(eNode);
			this.GetAllElemNode(eNode.Next, ref listENode);
			if (eNode.SubElementNode != null)
			{
				foreach (ElementNode eNode2 in eNode.SubElementNode)
				{
					this.GetAllElemNode(eNode2, ref listENode);
				}
			}
			return listENode;
		}

		private List<ElementNode> GetAllElemNodeReference(ElementNode eNode, ref List<ElementNode> listENode)
		{
			if (eNode != null)
			{
				if (eNode.Element is Pipe)
				{
					Line curve = ((eNode.Element as Pipe).Location as LocationCurve).Curve as Line;
					curve.GetEndPoint(0);
					XYZ xyz = (curve.GetEndPoint(0) + curve.GetEndPoint(1)) / 2.0;
					Pipe pipe = eNode.Element as Pipe;
					Line curve2 = (pipe.Location as LocationCurve).Curve as Line;
					XYZ xyz2 = (curve2.GetEndPoint(0) + curve2.GetEndPoint(1)) / 2.0;
					if (YJKRevitTools.isRiserPipe(pipe) && Math.Abs(xyz2.X - xyz.X) < 0.001 && Math.Abs(xyz2.Y - xyz.Y) < 0.001 && (xyz2.Z < xyz.Z || xyz2.IsAlmostEqualTo(xyz)))
					{
						listENode.Add(eNode);
					}
				}
				if (eNode.Next != null)
				{
					this.GetAllElemNodeReference(eNode.Next, ref listENode);
				}
				if (eNode.SubElementNode == null)
				{
					return listENode;
				}
				foreach (ElementNode eNode2 in eNode.SubElementNode)
				{
					this.GetAllElemNodeReference(eNode2, ref listENode);
				}
			}
			return listENode;
		}

		private bool ApproximateAB(double a, double b, double weight)
		{
			return Math.Abs(a - b) < weight;
		}

		private List<Element> riserPipeList = new List<Element>();
	}
}
